package com.foreveross.bsl.common.utils.bean;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Enumeration;
import java.util.UUID;
import java.util.zip.CRC32;
import java.util.zip.CheckedOutputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipOutputStream;

/**
 * 此类描述的是：zip 包解压和压缩处理工具类
 * 
 * @author: panhm@foreveross.com
 * @version: 2013-6-28 下午4:03:14
 */

public class ZipUtils {
	// private String basePath;
	// private String zipPath;

	/**
	 * 此方法描述的是：此方法描述的是：压缩逻辑处理
	 * 
	 * @author: panhm@foreveross.com
	 * @version: 2013-6-28 下午4:06:14
	 * @return 返回生成zip包的文件名
	 */

	public static void zipFile(File zipFile, String tempPath) {
		ZipOutputStream zipOut = null;
		try {
			FileOutputStream fileOut = new FileOutputStream(zipFile);
			CheckedOutputStream checkOut = new CheckedOutputStream(fileOut,
					new CRC32());
			zipOut = new ZipOutputStream(new BufferedOutputStream(checkOut));
			zipOut.setComment("this is a iknow exported zip file.");
			cycleFile(zipOut, tempPath, "");
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if (zipOut != null) {
				try {
					zipOut.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}

	/**
	 * 此方法描述的是：进行递归查询目录文件
	 * 
	 * @author: panhm@foreveross.com
	 * @version: 2013-6-28 下午3:52:48
	 */

	private static void cycleFile(ZipOutputStream zipOut, String filePath,
			String relativePath) {
		File file = new File(filePath);
		if (file.isFile()) { // 是文件则进行打包
			write(zipOut, filePath, relativePath);
		} else { // 是目录，继续进行查询子目录
			File[] children = file.listFiles();
			for (File f : children) {
				String tmpFilePath = filePath + File.separator + f.getName();
				String tmpRelativePath = null;
				if ("".equals(relativePath)) {
					tmpRelativePath = f.getName();
				} else {
					tmpRelativePath = relativePath + File.separator
							+ f.getName();
				}
				cycleFile(zipOut, tmpFilePath, tmpRelativePath);
			}
		}
	}

	/**
	 * 此方法描述的是：进行zip打包逻辑处理
	 * 
	 * @author: panhm@foreveross.com
	 * @version: 2013-6-28 下午3:51:55
	 */

	private static void write(ZipOutputStream zipOut, String filePath,
			String fileName) {
		FileInputStream fis = null;
		try {
			zipOut.putNextEntry(new ZipEntry(fileName));
			fis = new FileInputStream(filePath);
			int length = fis.available();
			if (length > 0) {
				byte[] temp = new byte[length];
				int count = 0;
				while ((count = fis.read(temp, 0, length)) != -1) {
					zipOut.write(temp, 0, count);
				}
			}

		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (fis != null) {
				try {
					fis.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}

	/**
	 * 此方法描述的是：解压zip包逻辑处理,返回解压后的临时路径
	 * 
	 * @author: panhm@foreveross.com
	 * @version: 2013-6-28 下午3:57:02
	 */

	@SuppressWarnings("rawtypes")
	public static String unzip(File zipfile) {

		String tempPath = UUID.randomUUID().toString();
		try {
			ZipFile zipFile = new ZipFile(zipfile);
			tempPath = zipfile.getPath() + tempPath;
			Enumeration emu = zipFile.entries();
			while (emu.hasMoreElements()) { // 遍历zip包文件
				ZipEntry entry = (ZipEntry) emu.nextElement();
				// 会把目录作为一个file读出一次，所以只建立目录就可以，之下的文件还会被迭代到。
				if (entry.isDirectory()) {
					new File(tempPath + File.separator + entry.getName())
							.mkdirs();
					continue;
				}
				BufferedInputStream bis = new BufferedInputStream(
						zipFile.getInputStream(entry));
				File file = new File(tempPath + File.separator
						+ entry.getName());
				// 加入这个的原因是zipfile读取文件是随机读取的，这就造成可能先读取一个文件
				// 而这个文件所在的目录还没有出现过，所以要建出目录来。
				File parent = file.getParentFile();
				if (parent != null && (!parent.exists())) {
					parent.mkdirs();
				}
				FileOutputStream fos = new FileOutputStream(file);
				BufferedOutputStream bos = new BufferedOutputStream(fos);
				int size = bis.available();
				if (size > 0) {
					int count;
					byte data[] = new byte[size];
					while ((count = bis.read(data, 0, size)) != -1) {
						bos.write(data, 0, count);
					}
				}
				bos.flush();
				bos.close();
				bis.close();
			}
			zipFile.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return tempPath;
	}

	/**
	 * 此方法描述的是：删除文件
	 * 
	 * @author: panhm@foreveross.com
	 * @version: 2013-6-28 下午5:39:55
	 */

	public static void del(String filepath) throws IOException {
		File f = new File(filepath);// 定义文件路径
		if (f.isFile()) {
			f.delete();
		} else {// 判断是文件还是目录
			// 若有则把文件放进数组，并判断是否有下级目录
			File delFile[] = f.listFiles();
			int i = f.listFiles().length;
			for (int j = 0; j < i; j++) {
				if (delFile[j].isDirectory()) {
					del(delFile[j].getAbsolutePath());// 递归调用del方法并取得子目录路径
				}
				delFile[j].delete();
			}
			f.delete();
		}
	}

	public static void main(String args[]) throws IOException {

		File zipfile = new File("d:\\a\\temp.zip");
		String temp = ZipUtils.unzip(zipfile);
		System.out.println(zipfile.renameTo(new File(
				"d:\\a\\temp_2013-06-18.zip")));

		File desczipfile = new File("d:\\a\\temp.zip");

		OutputStream ou = new FileOutputStream(temp + File.separator
				+ "aaa.json");
		ou.write("ssssssssss".getBytes());
		ou.close();
		ZipUtils.zipFile(desczipfile, temp);

		ZipUtils.del(temp);

	}
}
